package system.windows

import android.app.Activity
import android.app.ActivityManager
import android.content.Context
import android.content.Intent
import android.graphics.PixelFormat
import android.net.Uri
import android.os.Build
import android.provider.Settings
import android.util.Log
import android.view.Gravity
import android.view.View
import android.view.WindowManager
import android.widget.Toast
import io.flutter.embedding.engine.plugins.FlutterPlugin
import io.flutter.embedding.engine.plugins.activity.ActivityAware
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding
import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel
import io.flutter.plugin.common.MethodChannel.MethodCallHandler
import io.flutter.plugin.common.MethodChannel.Result


class SystemWindowsPlugin : FlutterPlugin, MethodCallHandler, ActivityAware {
    private lateinit var channel: MethodChannel
    private lateinit var context: Context
    private lateinit var activity: Activity
    private var rootView: View? = null
    private lateinit var windowManager: WindowManager


    private var textBox: TextBoxWindows? = null
    private var recordBox: RecordBoxWindows? = null

    override fun onAttachedToEngine(binding: FlutterPlugin.FlutterPluginBinding) {
        context = binding.applicationContext
        channel = MethodChannel(binding.binaryMessenger, "system.windows")
        channel.setMethodCallHandler(this)
        windowManager = context.getSystemService(Context.WINDOW_SERVICE) as WindowManager
    }

    override fun onMethodCall(call: MethodCall, result: Result) {
        var value = textBox?.onMethodCall(call, result)
        if (value != true) value = recordBox?.onMethodCall(call, result)
        if (value == true) return
        when (call.method) {
            "show" -> result.success(showWindow(call.arguments as Map<*, *>))
            "isActive" -> result.success(rootView != null)

            "toggle" -> {
                val state = call.arguments as Boolean
                if (state) {
                    /// 切换前台
                    front()
                } else {
                    /// 切换后台
                    val intent = Intent(Intent.ACTION_MAIN)
                    intent.addCategory(Intent.CATEGORY_HOME)
                    activity.startActivity(intent)
                }
                result.success(null)
            }

            "isSupported" -> result.success(checkPermission())
            "dispose" -> {
                close()
                result.success(true)
            }

            else -> result.success(null)
        }
    }

    private fun front() {
        val am = context.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
        am.moveTaskToFront(activity.taskId, ActivityManager.MOVE_TASK_WITH_HOME)
    }

    private fun showWindow(map: Map<*, *>): Boolean {
        if (rootView != null) {
            close()
        }
        if (!checkPermission()) {
            Toast.makeText(context, "请开启悬浮窗权限", Toast.LENGTH_SHORT).show()
            activity.startActivity(Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION).apply {
                data = Uri.parse("package:${context.packageName}")
            })
            return false
        }
        val displayMetrics = context.resources.displayMetrics

        val layoutParam = WindowManager.LayoutParams().apply {
            type = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY
            } else {
                WindowManager.LayoutParams.TYPE_PHONE
            }
            format = PixelFormat.RGBA_8888

            flags =
                WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL or WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
            width = dp2px((map["width"] as Double).toInt())
            height = dp2px((map["height"] as Double).toInt())
            gravity = Gravity.LEFT or Gravity.TOP
            x = dp2px((map["left"] as Double).toInt())
            y = dp2px((map["top"] as Double).toInt())

        }
        val windowsType = map["type"] as Int
        if (windowsType == 0) {
            textBox = TextBoxWindows(context, map, { close() }, { front() })
            rootView = textBox?.view
        } else if (windowsType == 1) {
            layoutParam.width = dp2px((map["width"] as Double).toInt())
            layoutParam.x = dp2px((map["left"] as Double).toInt())
            recordBox = RecordBoxWindows(context, map, { close() }, { front() })
            rootView = recordBox?.view
        }
        if (rootView == null) return false
        rootView?.setOnTouchListener(ViewTouchListener(layoutParam, windowManager))
        windowManager.addView(rootView, layoutParam)
        return true
    }


    private fun close() {
        if (!isNull(rootView?.windowToken)) {
            if (!isNull(windowManager)) {
                windowManager.removeView(rootView)
                textBox?.clear()
                rootView = null
                textBox = null
                recordBox = null
            }
        }
    }


    override fun onDetachedFromEngine(binding: FlutterPlugin.FlutterPluginBinding) {
        channel.setMethodCallHandler(null)
    }


    private fun checkPermission(): Boolean {
        var result = true
        if (Build.VERSION.SDK_INT >= 23) {
            try {
                val clazz: Class<*> = Settings::class.java
                val canDrawOverlays =
                    clazz.getDeclaredMethod("canDrawOverlays", Context::class.java)
                result = canDrawOverlays.invoke(null, context) as Boolean
            } catch (e: Exception) {
                Log.e("checkPermission", Log.getStackTraceString(e))
            }
        }
        return result
    }


    private fun isNull(any: Any?): Boolean = any == null

    private fun dp2px(value: Int): Int {
        val scale: Float = context.resources.displayMetrics.density
        return (value * scale + 0.5f).toInt()
    }

    override fun onAttachedToActivity(binding: ActivityPluginBinding) {
        activity = binding.activity
    }

    override fun onDetachedFromActivityForConfigChanges() {

    }

    override fun onReattachedToActivityForConfigChanges(binding: ActivityPluginBinding) {
        onAttachedToActivity(binding)
    }

    override fun onDetachedFromActivity() {
    }
}
